#include <algorithm>
#include <rtc_base/logging.h>
#include "ice/ice_agent.h"
#include "ice/ice_transport_channel.h"
namespace xrtc
{

    IceAgent::IceAgent(EventLoop *el, PortAllocator *allocator) : el_(el), allocator_(allocator)
    {
    }
    IceAgent::~IceAgent()
    {
        for (auto channel : channels_)
        {
            delete channel;
        }
        channels_.clear();
    }

    void IceAgent::OnCandidateAllocateDone(IceTransportChannel *channel, const std::vector<Candidate> &Candidates)
    {
        RTC_LOG(LS_INFO) << "candidate allocate done  :" << Candidates[0].ToString();
        SignalCandidateAllocateDone(this, channel->TransportName(), channel->Component(), Candidates);
    }

    bool IceAgent::CreateChannel(EventLoop *el, const std::string &transport_name, IceCandidateComponent component)
    {
        // 查询channel 是否存在
        if (GetChannel(transport_name, component))
        {
            return true;
        }
        // 不存在创建
        auto channel = new IceTransportChannel(el, allocator_, transport_name, component);

        channel->SignalCandidateAllocateDone.connect(this, &IceAgent::OnCandidateAllocateDone);
        channel->SignalReceivingState.connect(this, &IceAgent::OnIceRecevingState);
        channel->SignalWritableState.connect(this, &IceAgent::OnIceWritableState);
        channel->SignalIceStateChanged.connect(this, &IceAgent::OnIceStateChanged);

        channels_.push_back(channel);
        return true;
    }

    void IceAgent::OnIceRecevingState(IceTransportChannel *)
    {
        UpdateState();
    }
    void IceAgent::OnIceWritableState(IceTransportChannel *)
    {
        UpdateState();
    }
    void IceAgent::OnIceStateChanged(IceTransportChannel *)
    {
        UpdateState();
    }
    void IceAgent::UpdateState()
    {
        IceTransportState ice_state = IceTransportState::kNew;
        std::map<IceTransportState, int> ice_state_counts;

        for (auto channel : channels_)
        {
            ice_state_counts[channel->State()]++;
        }
        int total_ice_new = ice_state_counts[IceTransportState::kNew];
        int total_ice_checking = ice_state_counts[IceTransportState::kChecking];
        int total_ice_connected = ice_state_counts[IceTransportState::kConnected];
        int total_ice_completed = ice_state_counts[IceTransportState::kCompleted];
        int total_ice_failed = ice_state_counts[IceTransportState::kFailed];
        int total_ice_closed = ice_state_counts[IceTransportState::kClosed];
        int total_ice_disconnected = ice_state_counts[IceTransportState::kDisconnected];
        int total_ice = channels_.size();
        if (total_ice_failed > 0)
        {
            ice_state = IceTransportState::kFailed;
        }
        else if (total_ice_disconnected > 0)
        {
            ice_state = IceTransportState::kDisconnected;
        }
        else if (total_ice_new + total_ice_closed == total_ice)
        {
            ice_state = IceTransportState::kNew;
        }
        else if (total_ice_new + total_ice_checking > 0)
        {
            ice_state = IceTransportState::kChecking;
        }
        else if (total_ice_completed + total_ice_closed == total_ice)
        {
            ice_state = IceTransportState::kCompleted;
        }
        else if (total_ice_connected + total_ice_completed + total_ice_closed == total_ice)
        {
            ice_state = IceTransportState::kConnected;
        }

        RTC_LOG(LS_INFO) << "    ice_state : " << ice_state
                         << "    ice_state_: " << ice_state_;

        if (ice_state_ != ice_state)
        {
            // 为了保证不跳过k_connected状态
            if (ice_state_ == IceTransportState::kChecking && ice_state == IceTransportState::kCompleted)
            {
                SignalIceState(this, IceTransportState::kConnected);
            }
            ice_state_ = ice_state;
            SignalIceState(this, ice_state_);
        }
    }
    void IceAgent::SetIceParams(const std::string &transport_name, IceCandidateComponent component, const IceParameters &ice_params)
    {

        auto channel = GetChannel(transport_name, component);
        if (channel)
        {
            channel->SetIceParams(ice_params);
        }
    }
    void IceAgent::SetRemoteIceParams(const std::string &transport_name, IceCandidateComponent component, const IceParameters &ice_params)
    {
        auto channel = GetChannel(transport_name, component);
        if (channel)
        {
            channel->SetRemoteIceParams(ice_params);
        }
    }
    void IceAgent::GatheringCandidate() // 收集candidate
    {
        for (auto channel : channels_)
        {
            channel->GatheringCandidate();
        }
    }
    IceTransportChannel *IceAgent::GetChannel(const std::string &transport_name, IceCandidateComponent component)
    {
        auto iter = GetChannel_(transport_name, component);
        return iter == channels_.end() ? nullptr : *iter;
    }

    std::vector<IceTransportChannel *>::iterator IceAgent::GetChannel_(const std::string &transport_name, IceCandidateComponent component)
    {
        return std::find_if(channels_.begin(), channels_.end(),
                            [transport_name, component](IceTransportChannel *channel)
                            {
                                return (transport_name == channel->TransportName() && component == channel->Component());
                            });
    }

} // namespace xrtc